#include "context.h"
#include <stdarg.h>
#include <string.h>

#if defined(__x86_64__)
void CreateContext(SimpleUserContext *ucp, void (*func)(void))
{
    uintptr_t u_p =
        (uintptr_t)(ucp->uc_stack.ss_size - (sizeof(void *) << 1) + (uintptr_t)ucp->uc_stack.ss_sp);
    u_p = (u_p >> 4) << 4;
    ucp->registers[4] = (uintptr_t)(func);
    ucp->registers[5] = (uintptr_t)(u_p - sizeof(void *));
    *((void **)(ucp->registers[5])) = (void *)(NULL);
}
asm(".text                      \n\t"
    ".p2align 5                 \n\t"
#ifdef __APPLE__
    ".globl _SwapToContext      \n\t"
    "_SwapToContext:            \n\t"
#else
    ".globl SwapToContext       \n\t"
    "SwapToContext:             \n\t"
#endif
    "movq       (%rsp), %r8     \n\t"
    "leaq       0x8(%rsp), %rcx \n\t"
    "movq       %r12, (%rdi)    \n\t"
    "movq       %r13, 0x8(%rdi) \n\t"
    "movq       %r14, 0x10(%rdi)\n\t"
    "movq       %r15, 0x18(%rdi)\n\t"
    "movq       %r8,  0x20(%rdi)\n\t"
    "movq       %rcx, 0x28(%rdi)\n\t"
    "movq       %rbx, 0x30(%rdi)\n\t"
    "movq       %rbp, 0x38(%rdi)\n\t"
    "movq       0x0(%rsi),  %r12\n\t"
    "movq       0x8(%rsi),  %r13\n\t"
    "movq       0x10(%rsi), %r14\n\t"
    "movq       0x18(%rsi), %r15\n\t"
    "movq       0x20(%rsi), %rax\n\t"
    "movq       0x28(%rsi), %rcx\n\t"
    "movq       0x30(%rsi), %rbx\n\t"
    "movq       0x38(%rsi), %rbp\n\t"
    "movq       %rcx, %rsp      \n\t"
    "movq       %rdx, %rdi      \n\t"
    "jmp        *%rax           \n\t");
#else
#error "not implemented yet"
#endif
